package de.tud.stg.emergent.policy.utils;

import java.util.HashMap;

import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLStreamException;

import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.util.PolicyUtil;
import org.apache.neethi.Policy;

 
public class JaxbriUtils extends CommonPolicyUtils{

	
	private static volatile JaxbriUtils instance;
    
    public static JaxbriUtils getInstance() {
    	JaxbriUtils localInstance = instance;
    if (localInstance == null) {
        synchronized (JaxbriUtils.class) {
            localInstance = instance;
            if (localInstance == null) {
                instance = localInstance = new JaxbriUtils();
            }
        }
    }
    return localInstance;
} 
	
    
    public static final boolean deep_Normalize = true;
 
	public static final javax.xml.namespace.QName POLICY_QNAME = new javax.xml.namespace.QName(
			"http://schemas.xmlsoap.org/ws/2004/09/policy", "Policy", "ns4");
    
//	public static <T> T unmarshal(Class<T> docClass, InputStream inputStream)
//			throws JAXBException {
//		String packageName = docClass.getPackage().getName();
//		JAXBContext jc = JAXBContext.newInstance(packageName);
//		Unmarshaller u = jc.createUnmarshaller();
//		JAXBElement<T> doc = (JAXBElement<T>) u.unmarshal(inputStream);
//		return doc.getValue();
//	}
    
//public static org.xmlsoap.schemas.ws._2004._09.policy.Policy convertNeethiToUnmarshalJAXBPolicy(Policy neethiPolicy) {
//		
//		
//		OMElement policyComponentAsOMElement = null;
//		try {
//			policyComponentAsOMElement = PolicyUtil.getPolicyComponentAsOMElement(neethiPolicy);
//		} catch (XMLStreamException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (FactoryConfigurationError e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		
//		String policyString = policyComponentAsOMElement.toString();
//		
//		InputStream inPolicyStream = new ByteArrayInputStream(policyString.getBytes());
//		
//		org.xmlsoap.schemas.ws._2004._09.policy.Policy parsedPolicy = null;
//		try {
//			parsedPolicy = JaxbriUtils.unmarshal(org.xmlsoap.schemas.ws._2004._09.policy.Policy.class, inPolicyStream);
//		} catch (JAXBException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		
//	
//		
//		
//		return parsedPolicy;
//	}


//public static org.xmlsoap.schemas.ws._2004._09.policy.Policy getJaxbPolicyUnmarshalFromFile(String filePath){
//	
//	InputStream inputStream = null;
//	
//	try {
//		inputStream= new FileInputStream(filePath);
//	} catch (FileNotFoundException e) {
//		// TODO Auto-generated catch block
//		e.printStackTrace();
//	}
//	
//	org.xmlsoap.schemas.ws._2004._09.policy.Policy jaxbPolicy = null;
//	
//	try {
//		jaxbPolicy = JaxbriUtils.unmarshal(org.xmlsoap.schemas.ws._2004._09.policy.Policy.class, inputStream);
//	} catch (JAXBException e) {
//		// TODO Auto-generated catch block
//		e.printStackTrace();
//	}
//
//	return jaxbPolicy;
//}
	

	public static Policy convertJAXBToNeethiPolicy(org.xmlsoap.schemas.ws._2004._09.policy.Policy jaxbPolicy) {

		OMElement omPolicy = null;
		try {
			omPolicy = JaxbriUtils.getInstance().toOM(jaxbPolicy, false);
		} catch (AxisFault e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		Policy neethiPolicy = CommonPolicyUtils.getNeethiFromAxiomPolicy(omPolicy);

		return neethiPolicy;
	}


	public static org.xmlsoap.schemas.ws._2004._09.policy.Policy convertNeethiToJAXBPolicy(Policy neethiPolicy) {
       	
		 
		
		   OMElement policyComponentAsOMElement = convertNeethiToOMElement(neethiPolicy);
			
			
//			XMLStreamReader normalizedOMPolicyReader = policyComponentAsOMElement.getXMLStreamReaderWithoutCaching();
			
			try {
			
				HashMap<Object, Object> namespacesMap = new HashMap<Object, Object>();
	
				
				Object testPolicy = JaxbriUtils.getInstance().fromOM(policyComponentAsOMElement, org.xmlsoap.schemas.ws._2004._09.policy.Policy.class, namespacesMap);
 				org.xmlsoap.schemas.ws._2004._09.policy.Policy parsedPolicy  = (org.xmlsoap.schemas.ws._2004._09.policy.Policy) testPolicy;
				
 		
				return parsedPolicy;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
      
			return null;
			
		}

	
//	public static OMElement convertPolicytoOMElement(org.xmlsoap.schemas.ws._2004._09.policy.Policy policy) {
//		
//		OMElement omPolicyElement = null;
//		JAXBUtils utils = new JAXBUtils();
//
// 		
// 		try {
//			omPolicyElement = utils.toOM(policy, false);
//		} catch (AxisFault e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		 
//		return omPolicyElement;
//	}
	public static OMElement convertPolicytoOMElement(org.xmlsoap.schemas.ws._2004._09.policy.Policy policy) {
		
		OMElement omPolicyElement = null;
		JaxbriUtils utils = new JaxbriUtils();
		
		
		try {
			omPolicyElement = utils.toOM(policy, false);
		} catch (AxisFault e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return omPolicyElement;
	}
	
//	public static Policy convertPolicyToNeethi(org.xmlsoap.schemas.ws._2004._09.policy.Policy policy) {
//		
//		OMElement omPolicyElement = JAXBUtils.convertPolicytoOMElement(policy);
//		
//		Policy  neethiPolicy = PolicyUtil.getPolicyFromOMElement(omPolicyElement);
//		
//		return neethiPolicy;
//
//	}
	public static Policy convertPolicyToNeethi(org.xmlsoap.schemas.ws._2004._09.policy.Policy policy) {
		
		OMElement omPolicyElement = JaxbriUtils.convertPolicytoOMElement(policy);
		
		Policy  neethiPolicy = PolicyUtil.getPolicyFromOMElement(omPolicyElement);
		
		return neethiPolicy;
		
	}
	
	
	
	
	
	
	
	
	
	
	
	
//	
//	//--------------------------------------------------------------------------------------

	 private static final javax.xml.bind.JAXBContext wsContext;
     static {
         javax.xml.bind.JAXBContext jc;
         jc = null;
         try {
				jc = javax.xml.bind.JAXBContext.newInstance(
         org.xmlsoap.schemas.ws._2004._09.policy.Policy.class
				);
         }
         catch ( javax.xml.bind.JAXBException ex ) {
             System.err.println("Unable to create JAXBContext: " + ex.getMessage());
             ex.printStackTrace(System.err);
             Runtime.getRuntime().exit(-1);
         }
         finally {
             wsContext = jc;
			}
     }

     

             private org.apache.axiom.om.OMElement toOM(org.xmlsoap.schemas.ws._2004._09.policy.Policy param, boolean optimizeContent, javax.xml.namespace.QName methodQName)
             throws org.apache.axis2.AxisFault {
                 try {
                     javax.xml.bind.JAXBContext context = wsContext;
                     javax.xml.bind.Marshaller marshaller = context.createMarshaller();
                     marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FRAGMENT, Boolean.TRUE);

                     org.apache.axiom.om.OMFactory factory = org.apache.axiom.om.OMAbstractFactory.getOMFactory();

                     JaxbRIDataSource source = new JaxbRIDataSource( org.xmlsoap.schemas.ws._2004._09.policy.Policy.class,
                                                                     param,
                                                                     marshaller,
                                                                     methodQName.getNamespaceURI(),
                                                                     methodQName.getLocalPart());
                     org.apache.axiom.om.OMNamespace namespace = factory.createOMNamespace(methodQName.getNamespaceURI(),
                                                                        null);
                     return factory.createOMElement(source, methodQName.getLocalPart(), namespace);
                 } catch (javax.xml.bind.JAXBException bex){
                     throw org.apache.axis2.AxisFault.makeFault(bex);
                 }
             }

             private org.apache.axiom.om.OMElement toOM(org.xmlsoap.schemas.ws._2004._09.policy.Policy param, boolean optimizeContent)
                 throws org.apache.axis2.AxisFault {
                     try {
                         javax.xml.bind.JAXBContext context = wsContext;
                         javax.xml.bind.Marshaller marshaller = context.createMarshaller();
                         marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FRAGMENT, Boolean.TRUE);

                         org.apache.axiom.om.OMFactory factory = org.apache.axiom.om.OMAbstractFactory.getOMFactory();

                         JaxbRIDataSource source = new JaxbRIDataSource( org.xmlsoap.schemas.ws._2004._09.policy.Policy.class,
                                                                         param,
                                                                         marshaller,
                                                                         "http://schemas.xmlsoap.org/ws/2004/09/policy",
                                                                         "Policy");
                         org.apache.axiom.om.OMNamespace namespace = factory.createOMNamespace("http://schemas.xmlsoap.org/ws/2004/09/policy", null);
                         return factory.createOMElement(source, "Policy", namespace);
                     } catch (javax.xml.bind.JAXBException bex){
                         throw org.apache.axis2.AxisFault.makeFault(bex);
                     }
                 }


            


     
     private java.lang.Object fromOM (
         org.apache.axiom.om.OMElement param,
         java.lang.Class type,
         java.util.Map extraNamespaces) throws org.apache.axis2.AxisFault{
         try {
             javax.xml.bind.JAXBContext context = wsContext;
             javax.xml.bind.Unmarshaller unmarshaller = context.createUnmarshaller();

             return unmarshaller.unmarshal(param.getXMLStreamReaderWithoutCaching(), type).getValue();
         } catch (javax.xml.bind.JAXBException bex){
             throw org.apache.axis2.AxisFault.makeFault(bex);
         }
     }

     class JaxbRIDataSource implements org.apache.axiom.om.OMDataSource {
         /**
          * Bound object for output.
          */
         private final Object outObject;

         /**
          * Bound class for output.
          */
         private final Class outClazz;

         /**
          * Marshaller.
          */
         private final javax.xml.bind.Marshaller marshaller;

         /**
          * Namespace
          */
         private String nsuri;

         /**
          * Local name
          */
         private String name;

         /**
          * Constructor from object and marshaller.
          *
          * @param obj
          * @param marshaller
          */
         public JaxbRIDataSource(Class clazz, Object obj, javax.xml.bind.Marshaller marshaller, String nsuri, String name) {
             this.outClazz = clazz;
             this.outObject = obj;
             this.marshaller = marshaller;
             this.nsuri = nsuri;
             this.name = name;
         }

         public void serialize(java.io.OutputStream output, org.apache.axiom.om.OMOutputFormat format) throws javax.xml.stream.XMLStreamException {
             try {
                 marshaller.marshal(new javax.xml.bind.JAXBElement(
                         new javax.xml.namespace.QName(nsuri, name), outObject.getClass(), outObject), output);
             } catch (javax.xml.bind.JAXBException e) {
                 throw new javax.xml.stream.XMLStreamException("Error in JAXB marshalling", e);
             }
         }

         public void serialize(java.io.Writer writer, org.apache.axiom.om.OMOutputFormat format) throws javax.xml.stream.XMLStreamException {
             try {
                 marshaller.marshal(new javax.xml.bind.JAXBElement(
                         new javax.xml.namespace.QName(nsuri, name), outObject.getClass(), outObject), writer);
             } catch (javax.xml.bind.JAXBException e) {
                 throw new javax.xml.stream.XMLStreamException("Error in JAXB marshalling", e);
             }
         }

         public void serialize(javax.xml.stream.XMLStreamWriter xmlWriter) throws javax.xml.stream.XMLStreamException {
             try {
                 marshaller.marshal(new javax.xml.bind.JAXBElement(
                         new javax.xml.namespace.QName(nsuri, name), outObject.getClass(), outObject), xmlWriter);
             } catch (javax.xml.bind.JAXBException e) {
                 throw new javax.xml.stream.XMLStreamException("Error in JAXB marshalling", e);
             }
         }

         public javax.xml.stream.XMLStreamReader getReader() throws javax.xml.stream.XMLStreamException {
             try {
                 javax.xml.bind.JAXBContext context = wsContext;
                 org.apache.axiom.om.impl.builder.SAXOMBuilder builder = new org.apache.axiom.om.impl.builder.SAXOMBuilder();
                 javax.xml.bind.Marshaller marshaller = context.createMarshaller();
                 marshaller.marshal(new javax.xml.bind.JAXBElement(
                         new javax.xml.namespace.QName(nsuri, name), outObject.getClass(), outObject), builder);

                 return builder.getRootElement().getXMLStreamReader();
             } catch (javax.xml.bind.JAXBException e) {
                 throw new javax.xml.stream.XMLStreamException("Error in JAXB marshalling", e);
             }
         }
     }

}
